BUGFIX: template-require-iframe-title — flag title={{null|undefined|number}}#2731
Conversation
06219b7 to
1fd8b3b
Compare
… add allowWhitespaceOnlyTitle opt-out
Treat literal AST values that don't produce a meaningful accessible name
as invalid `<iframe title>` values:
- `GlimmerBooleanLiteral` / `GlimmerNullLiteral` / `GlimmerUndefinedLiteral` /
`GlimmerNumberLiteral` → flagged with a new `invalidTitleLiteral` messageId.
Coerce-to-string runtime values like "true" / "null" / "42" don't
describe the frame contents, regardless of framework behavior.
- `GlimmerStringLiteral` resolving to empty / whitespace → flagged as
`emptyTitle` (resolution shared with the text-node case via a
`processStaticTitle` helper). Closes a bypass that jsx-a11y already
catches via `getLiteralPropValue`.
Both literal classes apply to the bare-mustache `title={{x}}` form AND
the single-part concat `title="{{x}}"` form.
Whitespace-only static title (`title=" "`) is now opt-out via a new
`allowWhitespaceOnlyTitle: true` schema option. ACCNAME 1.2 §4.3.2 step
2I (Tooltip) does not whitespace-trim — so a 3-space accessible name is
spec-assigned. The check stays on by default as authoring hygiene; teams
that want strict spec parity can opt out. Empty-string `title=""` and
the non-string-literal cases above are not affected by this option —
they are always flagged as correctness.
Refs:
- WCAG SC 4.1.2: https://www.w3.org/TR/UNDERSTANDING-WCAG20/ensure-compat-rsv.html
- ACCNAME 1.2 §4.3.2: https://www.w3.org/TR/accname-1.2/#computation-steps
5dd3c75 to
19e44c4
Compare
|
|
||
| ## Configuration | ||
|
|
||
| - `allowWhitespaceOnlyTitle` (`boolean`, default `false`): when `true`, |
There was a problem hiding this comment.
why would we want to allow this?
There was a problem hiding this comment.
Hehe, basically because I (johan) didn't dare to have strict opinions on the behavior. but I feel somewhat silly defending it.
The option exists because the default is stricter than spec — it's an authoring-hygiene guard, not a normative requirement. Two relevant ACCNAME 1.2 steps from https://www.w3.org/TR/accname-1.2/#computation-steps. title=" " technically produces a three-space accessible name — spec-compliant, useless in practice. The option lets teams opt back to what the spec actually requires rather than our stricter default.
I doubt anyone will intentionally write a whitespace-only title. Should probably drop the option entirely and always flag it
…tle option Whitespace-only titles are never intentional and the option added API surface with no real-world use case. Always flag empty/whitespace title values as errors.
Note
This is part of a series where Claude has audited
eslint-plugin-emberagainst jsx-a11y, vuejs-accessibility, angular-eslint, lit-a11y and html-validate,ember-template-lint, and the HTML and WCAG specs.Summary
Premise 1:
<iframe>elements require an accessible name so assistive tech can convey their content. The normative source is WCAG SC 4.1.2 Name, Role, Value; Technique H64 is a sufficient technique citingtitleas one way to provide it.Premise 2: Mustache literal title values don't supply an author-intended name. At runtime Ember either drops the attribute when the bound value is nullish (no accessible name) or stringifies the literal to
"null"/"undefined"/"42"(a coerced placeholder). Empty string literals like{{""}}resolve to""— same effect astitle="".Premise 3: Today our rule only rejects
title={{false}}.title={{null}},title={{undefined}},title={{42}},title={{""}}, and theirtitle="{{x}}"concat equivalents silently pass.Conclusion: Treat
GlimmerBooleanLiteral,GlimmerNullLiteral,GlimmerUndefinedLiteral,GlimmerNumberLiteral, and empty/whitespaceGlimmerStringLiteralas invalid title values in both thetitle={{x}}andtitle="{{x}}"positions.Fix: extract
isInvalidTitleLiteralPath()for the four non-string literal types and a sharedprocessStaticTitle()helper that handles text-node, mustache-string-literal, and concat-string-literal forms uniformly. Empty / whitespace string literals follow the same emptiness path as text-nodetitle="".Tests cover each literal type × each syntax form (bare-mustache and concat).
Whitespace-only title — now opt-out via schema option
The rule previously flagged
title=" "(whitespace-only static) as a hard error. This is stricter than ACCNAME — ACCNAME 1.2 §4.3.2 step 2I (Tooltip) just says "return its value" with no trim (unlike step D AriaLabel, which has an explicitnor, when trimmed of whitespace, is not the empty stringcheck), so a 3-space accessible name is technically assigned. The check remains on by default as an authoring-hygiene guard (useless in practice), but teams that want spec-aligned behavior can opt out via the newallowWhitespaceOnlyTitle: trueoption. Empty-stringtitle="", the non-string literal cases above, and empty-string-literal mustaches are not affected by this option — they are always flagged as correctness.Prior art
Peers diverge materially on empty/non-string title handling. Don't assume parity:
iframe-has-titleif (title && typeof title === 'string')→ bail. Flagstitle=""(falsy), flagstitle={42}(not a string), flagstitle={null}(falsy). Does NOT flagtitle=" "(truthy string).iframe-has-titletitle === null || !["string","object"].includes(typeof title)→ flag. Does NOT flagtitle=""(typeof "string"). Flags:title='2'(number not a string).iframe-title!element.attribs.title || element.attribs.title === undefined. Flagstitle=""(falsy), does NOT flag non-string values (parse5 yields strings only).iframe-titleequivalent in the rules directory.